<template>
  <el-card>
    <div class="card-header">
      <span>用户管理</span>
    </div>
  </el-card>
  <el-card class="content">
    <el-form :inline="true" :model="listForm">
      <el-form-item label="用户名称">
        <el-input v-model="listForm.name" clearable/>
      </el-form-item>
      <el-form-item label="手机号码">
        <el-input v-model="listForm.mobile" clearable/>
      </el-form-item>
      <el-form-item>
        <perms-button
            perms="privilege:user:list"
            :type="Types.primary"
            :plain="true"
            @action="list"/>
      </el-form-item>
      <el-form-item>
        <perms-button
            perms="privilege:user:add"
            :type="Types.success"
            :plain="true"
            @action="showDialog('add')"/>
      </el-form-item>
    </el-form>
    <el-table
        :data="users"
        :border="true"
    >
      <template #empty>
        <el-empty/>
      </template>
      <el-table-column prop="name" label="用户名称" min-width="160"/>
      <el-table-column prop="mobile" label="手机号码" width="140"/>
      <el-table-column label="角色" min-width="160">
        <template #default="scope">
          <el-tag v-for="(role_id, idx) in scope.row.roles_id" :key="idx" size="small">{{roleName(role_id)}}</el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="department_name" label="部门" min-width="180"/>
      <el-table-column prop="status" label="用户状态" width="110" align="center">
        <template #default="scope">
          <el-switch
              v-model="scope.row.status"
              inline-prompt
              style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
              :active-value="10"
              :inactive-value="0"
              active-text="已启用"
              inactive-text="已禁用"
              @change="handleUserStatus(scope.row)"
          />
        </template>
      </el-table-column>
      <el-table-column prop="remark" label="备注"/>
      <el-table-column prop="created_at" label="创建时间" width="180" align="center">
        <template #default="scope">
          {{ timeFormat(scope.row.created_at) }}
        </template>
      </el-table-column>
      <el-table-column prop="updated_at" label="修改时间" width="180" align="center">
        <template #default="scope">
          {{ timeFormat(scope.row.updated_at) }}
        </template>
      </el-table-column>
      <el-table-column label="操作" width="240">
        <template #default="scope">
          <perms-link
              perms="privilege:user:update"
              :type="Types.success"
              @action="showDialog('update', scope.row)"/>
          <el-popconfirm
              :title="`确定删除用户[${scope.row.name}]吗?`"
              :icon="InfoFilled"
              icon-color="#F56C6C"
              cancel-button-text="取消"
              confirm-button-text="确认删除"
              cancel-button-type="info"
              confirm-button-type="danger"
              @confirm="deleteUser(scope.row.id)"
              width="300"
          >
            <template #reference>
              <perms-link
                  perms="privilege:user:delete"
                  :type="Types.danger"/>
            </template>
          </el-popconfirm>
          <perms-link
              perms="privilege:user:password:reset"
              :type="Types.warning"
              @action="changePassword(scope.row)"/>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
        class="page"
        v-model:current-page="listForm.page"
        v-model:page-size="listForm.size"
        :page-sizes="[30, 40, 50, 100]"
        :disabled="loading"
        background
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
        @size-change="list"
        @current-change="list"
    />
    <el-dialog
        :close-on-click-modal="false"
        v-model="visible"
        :title="dialogTitle"
        :draggable="true"
        :key="new Date().getTime()"
        width="600">
      <el-form :model="userForm" ref="formRef" :rules="rules" label-width="90">
        <el-row>
          <el-col :span="12">
            <el-form-item label="用户名称" prop="name">
              <el-input v-model="userForm.name" autocomplete="off"/>
            </el-form-item>
            <el-form-item label="所属部门" prop="department_id">
              <el-tree-select
                  :data="options"
                  :props="props"
                  v-model="userForm.department_id"
                  ref="departmentRef"
                  node-key="id"
                  default-expand-all
                  check-strictly
                  filterable
                  clearable
                  style="width: 360px">
                <template #default="{ node, data }">
                  <span>{{ data.name }}</span>
                  <span v-if="!node.isLeaf"> ({{ !!data.children ? data.children.length : 0 }}) </span>
                </template>
              </el-tree-select>
            </el-form-item>
            <el-form-item label="角色" prop="roles_id">
              <el-select
                  v-model="userForm.roles_id"
                  multiple
                  clearable
                  default-first-option
                  filterable>
                <el-option v-for="role in roles" :key="role.id" :label="role.name" :value="role.id" :disabled="role.status !== 20"></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="手机号码" prop="mobile">
              <el-input v-model="userForm.mobile" autocomplete="off"/>
            </el-form-item>
            <el-form-item label="状态" prop="status">
              <el-switch
                  v-model="userForm.status"
                  inline-prompt
                  style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
                  :active-value="10"
                  :inactive-value="0"
                  active-text="已启用"
                  inactive-text="已禁用"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="备注" prop="remark">
          <el-input type="textarea" v-model="userForm.remark" rows="5"/>
        </el-form-item>
      </el-form>
      <template #footer>
      <span class="dialog-footer">
        <el-button @click="visible = false">取消</el-button>
        <el-button type="primary" @click="handleSubmit">
          提交
        </el-button>
      </span>
      </template>
    </el-dialog>
  </el-card>

</template>

<script setup lang="ts">

import {DeleteRequest, ListRequest, ResetPasswordRequest, User, UserStatusRequest} from "@/interface/user";
import {onMounted, reactive, ref} from "vue";
import {ResetPasswordR, UserAddR, UserListR, UserRemoveR, UserStatusR, UserUpdateR} from "@/api/user";
import {CascaderInstance, ElMessage, ElMessageBox, FormInstance, FormRules} from "element-plus";
import {InfoFilled} from "@element-plus/icons-vue";
import * as dayjs from "dayjs";
import PermsButton from '@/components/PermsButton.vue'
import PermsLink from '@/components/PermsLink.vue'
import {RoleRequest} from "@/interface/role";
import {RoleListR, RolesR} from "@/api/role";
import {Department} from "@/interface/department";
import {DepartmentListR} from "@/api/department";
import {LoadDepartmentTree} from "@/utils/department";
import Node from "element-plus/es/components/cascader-panel/src/node";
import {Types} from "@/interface/enum";
const initListForm = () => {
  return <ListRequest>{
    page: 1,
    size: 10,
    name: '',
    mobile: '',
  }
}

const initUserForm = () => {
  return <User>{
    id: 0,
    name: '',
    // department_id: 0,
    department_name: '',
    roles_id: [],
    mobile: '',
    status: 10,
    remark: '',
    created_at: 0,
    updated_at: 0,
  }
}

const loading = ref<boolean>(false)
const visible = ref<boolean>(false)
const dialogTitle = ref<string>('')
const action = ref<string>('')

//表单
const formRef = ref<FormInstance>()
const listForm = ref<ListRequest>(initListForm())
const userForm = ref<User>(initUserForm())


//用户列表
const users = ref<User[]>([])
const total = ref<number>(0)

//角色列表
const roles = ref<RoleRequest[]>([])

//校验部门
const departmentValidator = (rule: any, value: any, callback: any) => {
  if ((userForm.value.department_id as number) < 1) {
    callback(new Error('必选'))
  } else {
    callback()
  }
}

//表单校验
const rules = reactive<FormRules>({
  name: [
    {required: true, message: '必填', type: "string", trigger: ['blur', 'change']}
  ],
  mobile: [
    {required: true, message: '必填', type: "string", trigger: ['blur', 'change']}
  ],
  status: [
    {required: true, message: '必填', type: "number", trigger: ['blur', 'change']}
  ],
  department_id: [
    // {required: true, message: '必选', validator:departmentValidator, trigger: ['blur', 'change']}
    {required: true, message: '必选', type: 'number', min: 1, trigger: ['blur', 'change']}
  ],
  roles_id: [
    {required: true, message: '必填', trigger: ['blur', 'change']},
    {type: "array", message: '类型错误', trigger: ['blur', 'change']},
  ]
})

//查询用户列表
const list = () => {
  loading.value = true
  UserListR(listForm.value).then(res => res.data).then(res => {
    loading.value = false
    switch (res.code) {
      case 200:
        users.value = res.data.list
        total.value = res.data.total
        break
      default:
        //ElMessage.error(res.msg)
    }
  }).catch(err => {
    loading.value = false
    ElMessage.error(err.toString())
  })
}

//查询全部角色
const getRoles = () => {
  loading.value = true
  RolesR().then(res => res.data).then(res => {
    loading.value = false
    switch (res.code) {
      case 200:
        roles.value = res.data.list
        break
      default:
        //ElMessage.error(res.msg)
    }
  }).catch(err => {
    loading.value = false
    ElMessage.error(err.toString())
  })
}

//部门:级联选择器
const options = ref<Department[]>()
const props = ref({label: 'name', value: 'id'})
//获取部门节点的完整级联路径
const parentIds = ref<Map<number, Array<number>>>(new Map<number, Array<number>>())
const cascaderParent = ref<Array<number>>([])
const loadParentIds = (departments: Department[]) => {
  // parentIds.value.set(0, [])
  departments.forEach((department) => {
    //查询上级级部门的路径
    let parentId: Array<number> = []
    if (!parentIds.value.has(department.parent_id)) {
      parentIds.value.set(department.parent_id, [])
    }

    parentId = parentIds.value.get(department.parent_id) as Array<number>
    if(department.parent_id>0){
      parentIds.value.set(department.id, [...parentId, department.parent_id])
    }else{
      parentIds.value.set(department.id, [...parentId])
    }
    // console.log('[id]', department.id, '=>[parent_id]', department.parent_id, '=> [path]', JSON.stringify(parentIds.value.get(department.id)))

    if (!!department.children && department.children.length > 0) {
      loadParentIds(department.children)
    }
  })
}

//查询部门列表
const getDepartments = () => {
  loading.value = true
  DepartmentListR().then(res => res.data).then(res => {
    switch (res.code) {
      case 200:
        //部门列表=>部门树
        let ds = res.data as Department[]
        // console.log('部门列表:', ds)
        let parents = ds.filter((m) => m.parent_id === 0)
        let children = ds.filter((m) => m.parent_id !== 0)

        LoadDepartmentTree(parents, children)

        options.value = parents

        parentIds.value = new Map<number, Array<number>>()
        loadParentIds(parents)
        break
      default:
        //ElMessage.error(res.msg)
    }
  })
}

const showDialog = (act: string, user?: User) => {
  switch (act) {
    case 'add':
      action.value = act
      userForm.value = initUserForm()
      visible.value = true
      break
    case 'update':
      action.value = act
      userForm.value = JSON.parse(JSON.stringify(user as User))
      visible.value = true
      cascaderParent.value = parentIds.value.get(user!.department_id as number) as Array<number>
      break
    default:
      ElMessage.error('未知操作')
  }
}

const departmentRef = ref<CascaderInstance>()
const handleSubmit = () => {
  //设置 department_id
  // let nodes = departmentRef.value?.getCheckedNodes(false) //是否只监测leaf节点
  // if (!!nodes && nodes.length > 0) {
  //   userForm.value.department_id = (nodes.pop() as Node).value as number
  // } else {
  //   userForm.value.department_id = 0
  // }
  
  formRef.value?.validate((isValid) => {
    if(!isValid){
      return
    }
    switch (action.value) {
      case 'add':
        addUser()
        break
      case 'update':
        editUser()
        break
      default:
        ElMessage.warning('未知操作')
    }
  })


}

//新增用户
const addUser = () => {
  UserAddR(userForm.value).then(res => res.data).then(res => {
    switch (res.code) {
      case 200:
        ElMessage.success(res.msg)
        list()
        visible.value = false
        defaultPasswordTip()
        break
      default:
        // ElMessage.error(res.msg)
    }
  })
}

//修改
const editUser = () => {
  UserUpdateR(userForm.value).then(res => res.data).then(res => {
    switch (res.code) {
      case 200:
        ElMessage.success(res.msg)
        list()
        visible.value = false
        break
      default:
        // ElMessage.error(res.msg)
    }
  })
}

//默认密码提示
const defaultPasswordTip = () => {
  ElMessageBox.alert('默认密码：123456.', '提示', {
    confirmButtonText: '了解',
  })
}

//删除用户
const deleteUser = (id: number) => {
  if (id <= 0) {
    ElMessage.error('用户不存在')
    return
  }

  let req = <DeleteRequest>{id: id}

  UserRemoveR(req).then(res => res.data).then(res => {
    switch (res.code) {
      case 200:
        ElMessage.success(res.msg)
        list()
        break
      default:
        //ElMessage.error(res.msg)
    }
  })
}

//密码校验
const validdatePass = (pass: string) => {
  if (pass.length < 6 || pass.length > 18) {
    return '密码长度：6-18位'
  }

  return true
}

//重置密码
const changePassword = (user: User) => {
  let req = <ResetPasswordRequest>({id: user.id, password: ''})
  ElMessageBox.prompt(`请输入[${user.name}]的新密码：`, '重置密码', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    draggable: true,
    showClose: false,
    inputValidator: validdatePass
  }).then(({value}) => {
    req.password = value
    submitPassword(req)
    // ResetPasswordR(req).then(res=>res.data).then(res=>{
    //   switch (res.code) {
    //     case 200:
    //       ElMessage.success(res.msg)
    //       break
    //     default:
    //       ElMessage.error(res.msg)
    //   }
    // }).catch(err => {
    //   ElMessage.error(err)
    // })
  }).catch(err => {
    console.log(err.toString())
  })
}

const submitPassword = (req: ResetPasswordRequest) => {
  ResetPasswordR(req).then(res => res.data).then(res => {
    switch (res.code) {
      case 200:
        ElMessage.success(res.msg)
        break
      default:
        //ElMessage.error(res.msg)
    }
  }).catch(err => {
    ElMessage.error(err)
  })
}

//更改用户状态
const handleUserStatus = (user: User) => {
  if (user.id as number <= 0) {
    ElMessage.warning('用户不存在')
    return false
  }

  loading.value = true
  let req = <UserStatusRequest>({id: user.id, status: user.status})
  UserStatusR(req).then(res => res.data).then(res => {
    loading.value = false
    switch (res.code) {
      case 200:
        ElMessage.success(res.msg)
        list()
        break
      default:
        //ElMessage.error(res.msg)
    }

  }).catch(err => {
    loading.value = false
    ElMessage.error(err.toString())
  })
}

onMounted(() => {
  list()
  getRoles()
  getDepartments()
})


//时间格式
const timeFormat = (timestamp: number) => {
  return dayjs.unix(timestamp).format('YYYY-MM-DD HH:mm:ss')
}

//角色名称
const roleName = (role_id:number) => {
  return roles.value.filter((role)=>role.id===role_id).map((role)=>role.name).pop()
}
</script>

<style scoped lang="less">
.el-card {
  margin-bottom: 10px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.page {
  margin-top: 10px;
}

.links {
  padding-right: 10px;
}

</style>